
`timescale 1 ps/1 ps

module axi_tx_arbiter 
(
    input                       clk,
    input                       rst,

    input       [7:0]           s0_axis_tdata,
    input                       s0_axis_tvalid,
    output reg                  s0_axis_tready,
    input                       s0_axis_tlast,
    input                       s0_axis_tfirst,

    input       [7:0]           s1_axis_tdata,
    input                       s1_axis_tvalid,
    output  reg                 s1_axis_tready,
    input                       s1_axis_tlast,
    input                       s1_axis_tfirst,

    input       [7:0]           s2_axis_tdata,
    input                       s2_axis_tvalid,
    output  reg                 s2_axis_tready,
    input                       s2_axis_tlast,
    input                       s2_axis_tfirst,

    output  reg [7:0]           m_axis_tdata,
    output  reg                 m_axis_tvalid,
    input                       m_axis_tready,
    output  reg                 m_axis_tlast,
    output  reg                 m_axis_tfirst
);

localparam  IDLE  = 0,
            S0    = 1,
            S1    = 2,
            S2    = 3;

reg [S2:0] cs,ns;

always@(posedge clk)
begin
  if(rst)  
      cs <= 'd1;
  else        
      cs <= ns;
end

always @(*) 
begin
  ns = 'd0;
  case(1'b1)
    cs[IDLE]:  
    begin
        if(s0_axis_tvalid)                                
            ns[S0]    = 1'b1;
        else if(s1_axis_tvalid)                           
            ns[S1]    = 1'b1;
        else if(s2_axis_tvalid)                           
            ns[S2]    = 1'b1;
        else                                              
            ns[IDLE]  = 1'b1;
    end
    cs[S0]:    
    begin
        if(m_axis_tvalid & m_axis_tready & m_axis_tlast)  
            ns[IDLE]  = 1'b1;
        else                                              
            ns[S0]    = 1'b1;
    end
    cs[S1]:    
    begin
        if(m_axis_tvalid & m_axis_tready & m_axis_tlast)  
            ns[IDLE]  = 1'b1;
        else                                              
            ns[S1]    = 1'b1;
    end
    cs[S2]:    
    begin
        if(m_axis_tvalid & m_axis_tready & m_axis_tlast)  
            ns[IDLE]  = 1'b1;
        else                                              
            ns[S2]    = 1'b1;
    end
    default: ns[IDLE]  = 1'b1;
  endcase
end

always @(*)
begin
    case(1'b1)
        cs[S0]:  
        begin
            m_axis_tdata    = s0_axis_tdata;
            m_axis_tvalid   = s0_axis_tvalid;
            m_axis_tlast    = s0_axis_tlast;
            m_axis_tfirst   = s0_axis_tfirst;
            s0_axis_tready  = m_axis_tready;
            s1_axis_tready  = 0;
            s2_axis_tready  = 0;
        end
        cs[S1]:  
        begin
            m_axis_tdata    = s1_axis_tdata;
            m_axis_tvalid   = s1_axis_tvalid;
            m_axis_tlast    = s1_axis_tlast;
            m_axis_tfirst   = s1_axis_tfirst;
            s0_axis_tready  = 0;
            s2_axis_tready  = 0;
            s1_axis_tready  = m_axis_tready;
        end
        cs[S2]:  
        begin
            m_axis_tdata    = s2_axis_tdata;
            m_axis_tvalid   = s2_axis_tvalid;
            m_axis_tlast    = s2_axis_tlast;
            m_axis_tfirst   = s2_axis_tfirst;
            s0_axis_tready  = 0;
            s1_axis_tready  = 0;
            s2_axis_tready  = m_axis_tready;
        end
        default:  
        begin
            m_axis_tdata    = s0_axis_tdata;
            m_axis_tvalid   = 1'b0;
            m_axis_tlast    = 1'b0;
            m_axis_tfirst   = 1'b0;
            s0_axis_tready  = 1'b0;
            s1_axis_tready  = 1'b0;
            s2_axis_tready  = 1'b0;
        end
    endcase
end

endmodule
